package com.ming.common.beetl.controller;

import com.alibaba.fastjson.JSON;
import com.ming.common.Options;
import com.ming.common.SelectOptionItem;
import com.ming.common.SortBy;
import com.ming.common.beetl.entity.IvyDbSql;
import com.ming.common.beetl.entity.IvyDbSqlItem;
import com.ming.common.beetl.entity.IvyDbSqlOper;
import com.ming.common.beetl.execption.SQLBuildException;
import com.ming.common.beetl.util.BeetlSqlUtil;
import com.ming.common.beetl.util.Result;
import com.ming.common.beetl.util.StrUtil;
import com.ming.common.beetl.vo.IvyDbSqlVo;
import com.ming.common.util.ClassFieldUtil;
import com.ming.common.xxljob.annotation.PermissionLimit;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.SQLReady;
import org.beetl.sql.core.page.PageResult;
import org.beetl.sql.core.query.LambdaQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/db/sql")
public class IvyDbSqlController {

    private static final Logger LOG = LoggerFactory.getLogger(IvyDbSqlController.class);

    @Resource
    private SQLManager sqlManager;

    @PostMapping("/option")
    @PermissionLimit(limit = false)
    public Result<?> option(@RequestBody Map<String,Object> map) {
        return Result.OK(ClassFieldUtil.getFieldAnnoDescribe(IvyDbSql.class, map));
    }

    @PostMapping("/queryTypeOption")
    @PermissionLimit(limit = false)
    public Result<?> queryTypeOption(@RequestBody Map<String,Object> map) {
        map.put("fieldNames","column,where,orderBy,limit,groupBy");
        return Result.OK(ClassFieldUtil.getFieldAnnoDescribe(IvyDbSqlOper.class, map));
    }

    @PostMapping("/page")
    @PermissionLimit(limit = false)
    public Result<PageResult<IvyDbSql>> page(@RequestBody IvyDbSqlVo vo){
        LambdaQuery<IvyDbSql> lambdaQuery = sqlManager.lambdaQuery(IvyDbSql.class);
        lambdaQuery.andEq(IvyDbSql::getSqlManagerId, LambdaQuery.filterEmpty(vo.getSqlManagerId()));
        lambdaQuery.andEq(IvyDbSql::getSqlLanguage, LambdaQuery.filterEmpty(vo.getSqlLanguage()));
        lambdaQuery.andLike(IvyDbSql::getTableName, LambdaQuery.filterLikeEmpty(vo.getTableName()));
        lambdaQuery.andEq(IvyDbSql::getTableType, LambdaQuery.filterEmpty(vo.getTableType()));
        lambdaQuery.andEq(IvyDbSql::getSqlId, LambdaQuery.filterEmpty(vo.getSqlId()));
        lambdaQuery.andLike(IvyDbSql::getSqlName, LambdaQuery.filterLikeEmpty(vo.getSqlName()));
        lambdaQuery.andEq(IvyDbSql::getSqlType, LambdaQuery.filterEmpty(vo.getSqlType()));
        lambdaQuery.andEq(IvyDbSql::getDisabled, LambdaQuery.filterEmpty(vo.getDisabled()));
        Options options = vo.getOptions();
        List<SortBy> sortBy = options.getSortBy();
        for (SortBy sort : sortBy) {
            if ("desc".equalsIgnoreCase(sort.getOrder())) {
                lambdaQuery.desc(StrUtil.camelToSnake(sort.getKey()));
            } else {
                lambdaQuery.asc(StrUtil.camelToSnake(sort.getKey()));
            }
        }
        PageResult<IvyDbSql> page = lambdaQuery.page(options.getPage(), options.getItemsPerPage());
        return Result.OK(page);
    }

    @PostMapping("/add")
    @PermissionLimit(limit = false)
    public Result<?> add(@RequestBody IvyDbSql item){
        LambdaQuery<IvyDbSql> lambdaQuery = sqlManager.lambdaQuery(IvyDbSql.class);
        lambdaQuery.andEq(IvyDbSql::getSqlId, item.getSqlId());
        long count = lambdaQuery.count();
        if(count > 0){
            return Result.error("新增失败：SqlId已存在");
        }
        LambdaQuery<IvyDbSql> query = sqlManager.lambdaQuery(IvyDbSql.class);
        if(item.getDisabled() == null){
            item.setDisabled(false);
        }
        handler(item);
        int i = query.insert(item);
        return Result.OK(i);
    }

    @PostMapping("/update")
    @PermissionLimit(limit = false)
    public Result<Object> update(@RequestBody IvyDbSql item){
        LambdaQuery<IvyDbSql> lambdaQuery = sqlManager.lambdaQuery(IvyDbSql.class);
        lambdaQuery.andNotEq(IvyDbSql::getId, item.getId());
        lambdaQuery.andEq(IvyDbSql::getSqlId, item.getSqlId());
        long count = lambdaQuery.count();
        if(count > 0){
            return Result.error("更新失败：SqlId已存在");
        }
        handler(item);
        int i = sqlManager.updateById(item);
        return Result.OK("更新成功", i);
    }

    private void handler(IvyDbSql item){

    }

    @PostMapping("/delete")
    @PermissionLimit(limit = false)
    public Result<Integer> delete(@RequestBody IvyDbSql item){
        LambdaQuery<IvyDbSql> lambdaQuery = sqlManager.lambdaQuery(IvyDbSql.class);
        lambdaQuery.andEq(IvyDbSql::getId, item.getId());
        int i = lambdaQuery.delete();
        return Result.OK("删除成功",i);
    }

    @PostMapping("/column/list")
    @PermissionLimit(limit = false)
    public Result<?> columnList(@RequestBody IvyDbSql item){
        List<SelectOptionItem> itemList = BeetlSqlUtil.NEW().sqlManagerId(item.getSqlManagerId())
                .tableName(item.getTableName()).getColNames();
        return Result.OK(itemList);
    }

    @PostMapping("/build")
    @PermissionLimit(limit = false)
    public Result<?> build(@RequestBody IvyDbSqlVo item){
        String sql = null;
        try {
            sql = BeetlSqlUtil.NEW().ivyDbSql(item).buildSql();
        } catch (SQLBuildException e) {
            return Result.error(e.getMessage());
        }
        if(StrUtil.isNotEmpty(sql)){
            Map<String, List<IvyDbSqlItem>> map = new HashMap<>();
            map.put("column", peek(item.getColumnList()));
            map.put("where", peek(item.getWhereList()));
            map.put("groupBy", peek(item.getGroupByList()));
            map.put("orderBy", peek(item.getOrderByList()));
            map.put("limit", peek(item.getLimitList()));
            String sqlJson = JSON.toJSONString(map);
            sqlManager.executeUpdate(new SQLReady("UPDATE ivy_db_sql SET sql_template = ?,sql_json = ? WHERE `id` = ?",item.getSqlTemplate(), sqlJson, item.getId()));
        }
        return Result.OK(sql);
    }

    private List<IvyDbSqlItem> peek(List<IvyDbSqlItem> list){
        AtomicInteger index = new AtomicInteger(1);
        return list.stream().peek(m -> m.setIndex(index.getAndIncrement())).collect(Collectors.toList());
    }

    @PostMapping("/exec")
    @PermissionLimit(limit = false)
    public Result<?> exec(@RequestBody IvyDbSql vo){
        /*SQLManager manager = CacheSqlManagerUtil.getCache(vo.getSmBeanName(), SQLManager.class);
        String sql = vo.getSourceSql();
        if(cn.hutool.core.util.StrUtil.isBlank(sql)){
            return Result.error("SQL语句不能为空！");
        }
        sql = sql.trim();
        LogInfo logInfo = LogInit.getLogInfo();
        if(sql.toLowerCase().startsWith("select")){
            List<Map> returnVal = manager.execute(new SQLReady(sql), Map.class);
            return Result.OK(LogInit.getResultVal(returnVal,logInfo));
        }else{
            int returnVal = manager.executeUpdate(new SQLReady(sql));
            return Result.OK(LogInit.getResultVal(returnVal,logInfo));
        }*/
        return null;
    }
}
